package com.beiming.libra.service.impl;

import com.beiming.libra.common.Assert;
import com.beiming.libra.common.constants.ValidateMessage;
import com.beiming.libra.common.enums.ErrorCode;
import com.beiming.libra.common.enums.SMSEnum;
import com.beiming.libra.common.enums.StatusEnum;
import com.beiming.libra.common.enums.UserRelationEnum;
import com.beiming.libra.common.enums.UserTypeEnum;
import com.beiming.libra.common.enums.VerifyEnum;
import com.beiming.libra.common.mail.model.Email;
import com.beiming.libra.common.mail.service.IMailService;
import com.beiming.libra.common.page.Page;
import com.beiming.libra.common.page.PageResult;
import com.beiming.libra.common.utils.BeanConvertUtils;
import com.beiming.libra.common.utils.CommonsUtils;
import com.beiming.libra.dao.ArbitrationUserProxyMapper;
import com.beiming.libra.dao.ArbitrationUserRelationMapper;
import com.beiming.libra.dao.UserDetailMapper;
import com.beiming.libra.dao.UserMapper;
import com.beiming.libra.domain.ArbitrationUserRelation;
import com.beiming.libra.domain.User;
import com.beiming.libra.domain.UserDetail;
import com.beiming.libra.domain.dto.requestdto.UserRelationRequestDTO;
import com.beiming.libra.domain.dto.requestdto.UserRequestDTO;
import com.beiming.libra.domain.dto.responsedto.UserProxyResponseDTO;
import com.beiming.libra.domain.dto.responsedto.UserRelationResponseDTO;
import com.beiming.libra.redis.enums.RedisKey;
import com.beiming.libra.service.RedisService;
import com.beiming.libra.service.SMSService;
import com.beiming.libra.service.UserProxyService;
import com.beiming.libra.service.UserRelationService;
import com.beiming.libra.service.VerifyService;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.TimeUnit;
import javax.annotation.Resource;
import java.util.List;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * @author Rimon Date : 2018/6/5 11:30
 */
@Service
public class UserRelationServiceImpl implements UserRelationService {

  private static final int RANDOM_MIN = 100000;
  private static final int RANDOM_MAX = 900000;

  @Value("${sms.code.expireMinutes}")
  private int smsCodeExpireMinutes;
  @Resource
  private ArbitrationUserRelationMapper userRelationMapper;
  @Resource
  private ArbitrationUserProxyMapper userProxyMapper;
  @Resource
  private UserMapper userMapper;
  @Resource
  private UserDetailMapper userDetailMapper;
  @Resource
  private RedisService redisService;
  @Resource
  private SMSService smsService;
  @Resource
  private IMailService iMailService;
  @Resource
  private UserProxyService userProxyService;
  @Resource
  private VerifyService verifyService;

  @Override
  public List<UserRelationResponseDTO> getUserRelations(String userId) {
    Assert.isNotNull(userId, ErrorCode.ILLEGAL_PARAMETER, ValidateMessage.ID_NOT_BLANK);
    return userRelationMapper.getUserRelation(userId);
  }

  @Override
  public PageResult<UserRelationResponseDTO> listParty(String userId, int pageSize,
      int pageNo) {
    UserRelationRequestDTO userRelationRequestDTO = new UserRelationRequestDTO();
    List<UserRelationResponseDTO> list = userRelationMapper.getUserRelation(userId,
            (pageNo - 1)
                * pageSize, pageSize);
    userRelationRequestDTO.setPageNo(pageNo);
    userRelationRequestDTO.setPageSize(pageSize);
    PageResult<UserRelationResponseDTO> pageResult = new PageResult<UserRelationResponseDTO>();
    pageResult.setList(list);
    int total = userRelationMapper.listPartyCount(userId);
    Page page = new Page();
    page.setPageNo(userRelationRequestDTO.getPageNo());
    page.setPageSize(userRelationRequestDTO.getPageSize());
    page.setTotalRecords(total);
    pageResult.setPage(page);
    return pageResult;
  }

  @Override
  public PageResult<UserRelationResponseDTO> listRelation(UserRequestDTO userRequestDTO) {
    if (!StringUtils.isEmpty(userRequestDTO.getRelationType())) {
      if (UserRelationEnum.PARTY.getCode().equals(userRequestDTO.getRelationType())) {
        return listParty(userRequestDTO.getUserId(), userRequestDTO.getPageSize(), userRequestDTO.getPageNo());
      }
      if (UserRelationEnum.PROXY.getCode().equals(userRequestDTO.getRelationType())) {
        return userProxyService.listParty(userRequestDTO.getUserId(), userRequestDTO.getPageSize(), userRequestDTO.getPageNo());
      }
    }
    UserRelationRequestDTO userRelationRequestDTO = new UserRelationRequestDTO();
    List<UserRelationResponseDTO> list =
        userRelationMapper.listRelation(userRequestDTO.getUserId(),
            (userRequestDTO.getPageNo() - 1)
                * userRequestDTO.getPageSize(), userRequestDTO.getPageSize());
    userRelationRequestDTO.setPageNo(userRequestDTO.getPageNo());
    userRelationRequestDTO.setPageSize(userRequestDTO.getPageSize());
    PageResult<UserRelationResponseDTO> pageResult = new PageResult<UserRelationResponseDTO>();
    pageResult.setList(list);
    int total = userRelationMapper.listRelationCount(userRequestDTO.getUserId());
    Page page = new Page();
    page.setPageNo(userRelationRequestDTO.getPageNo());
    page.setPageSize(userRelationRequestDTO.getPageSize());
    page.setTotalRecords(total);
    pageResult.setPage(page);
    return pageResult;
  }

  @Override
  public UserRelationResponseDTO getUserRelationDetail(String id) {
    Assert.isNotNull(id, ErrorCode.ILLEGAL_PARAMETER, ValidateMessage.ID_NOT_BLANK);
    return userRelationMapper.getUserRelationDetail(id);
  }

  @Override
  public List<UserRelationResponseDTO> getOrganizationRelations(String userId) {
    return null;
  }

  @Override
  public List<UserRelationResponseDTO> getAllRelations(String userId) {
    return null;
  }

  @Override
  public void delete(String id) {
    Assert.isNotNull(id, ErrorCode.ILLEGAL_PARAMETER, ValidateMessage.ID_NOT_BLANK);
    ArbitrationUserRelation arbitrationUserRelation = userRelationMapper.selectByPrimaryKey(id);
    Assert.isNotNull(arbitrationUserRelation, ErrorCode.RESULT_EMPTY, "当事人不存在");
    arbitrationUserRelation.setStatus("1");
    userRelationMapper.updateByPrimaryKey(arbitrationUserRelation);
  }

  @Override
  @Transactional(rollbackFor = Exception.class)
  public void insertParty(UserRelationRequestDTO userRelationRequestDTO, String userId) {
    Assert.isNotNull(userRelationRequestDTO, ErrorCode.ILLEGAL_PARAMETER,
        ValidateMessage.ID_NOT_BLANK);
    Assert.isNotNull(userId, ErrorCode.ILLEGAL_PARAMETER, ValidateMessage.ID_NOT_BLANK);
    List<User> userRepeat = userMapper
        .selectByMobilePhoneAndType(userRelationRequestDTO.getMobilePhone(),
            userRelationRequestDTO.getUserType());
    Assert.isListEmpty(userRepeat, ErrorCode.MOBILE_EXITS, "该手机号已注册");
    User user = new User();
    user.setId(CommonsUtils.get32BitUUID());
    user.setMobilePhone(userRelationRequestDTO.getMobilePhone());
    user.setUserType(userRelationRequestDTO.getUserType());
    userRelationRequestDTO.setId(CommonsUtils.get32BitUUID());
    userRelationRequestDTO.setUserId(user.getId());
    UserDetail userDetail = BeanConvertUtils.copyBean(userRelationRequestDTO, UserDetail.class);
    ArbitrationUserRelation arbitrationUserRelation = new ArbitrationUserRelation();
    arbitrationUserRelation.setId(CommonsUtils.get32BitUUID());
    arbitrationUserRelation.setUserId(userId);
    arbitrationUserRelation.setRelUserId(user.getId());
    arbitrationUserRelation.setStatus(StatusEnum.USED.getCode());
    arbitrationUserRelation.setCreateTime(new Date());
    arbitrationUserRelation.setVersion(0);
    this.userDetailMapper.insert(userDetail);
    this.userMapper.insert(user);
    this.userRelationMapper.insert(arbitrationUserRelation);
  }

  @Override
  @Transactional(rollbackFor = Exception.class)
  public void updateParty(UserRelationRequestDTO userRelationRequestDTO) {
    Assert.isNotNull(userRelationRequestDTO.getUserId(), ErrorCode.ILLEGAL_PARAMETER,
        ValidateMessage.ID_NOT_BLANK);
    User user = userMapper.selectByPrimaryKey(userRelationRequestDTO.getUserId());
    if (!user.getMobilePhone().equals(userRelationRequestDTO.getMobilePhone())) {
      List<User> userRepeat = userMapper
          .selectByMobilePhoneAndType(userRelationRequestDTO.getMobilePhone(),
              userRelationRequestDTO.getUserType());
      Assert.isListEmpty(userRepeat, ErrorCode.MOBILE_EXITS, "该手机号已注册");
    }
    Assert.isNotNull(user, ErrorCode.RESULT_EMPTY, ValidateMessage.ID_NOT_BLANK);
    List<UserDetail> userDetailList = userDetailMapper.selectByUserId(user.getId());
    Assert.isNotNull(userDetailList, ErrorCode.RESULT_EMPTY, ValidateMessage.ID_NOT_BLANK);
    UserDetail userDetail = userDetailList.get(0);
    if (!StringUtils.isEmpty(userRelationRequestDTO.getUserType())) {
      user.setUserType(userRelationRequestDTO.getUserType());
      userDetail.setUserType(userRelationRequestDTO.getUserType());
    }
    if (!StringUtils.isEmpty(userRelationRequestDTO.getUserName())) {
      userDetail.setUserName(userRelationRequestDTO.getUserName());
    }
    if (!StringUtils.isEmpty(userRelationRequestDTO.getSex())) {
      userDetail.setSex(userRelationRequestDTO.getSex());
    }
    if (!StringUtils.isEmpty(userRelationRequestDTO.getCivilFamily())) {
      userDetail.setCivilFamily(userRelationRequestDTO.getCivilFamily());
    }
    if (!StringUtils.isEmpty(userRelationRequestDTO.getResponsibleUser())) {
      userDetail.setResponsibleUser(userRelationRequestDTO.getResponsibleUser());
    }
    if (!StringUtils.isEmpty(userRelationRequestDTO.getResponsiblePhone())) {
      userDetail.setResponsiblePhone(userRelationRequestDTO.getResponsiblePhone());
    }
    if (!StringUtils.isEmpty(userRelationRequestDTO.getLegalUser())) {
      userDetail.setLegalUser(userRelationRequestDTO.getLegalUser());
    }
    if (!StringUtils.isEmpty(userRelationRequestDTO.getLegalUserJob())) {
      userDetail.setLegalUserJob(userRelationRequestDTO.getLegalUserJob());
    }
    if (!StringUtils.isEmpty(userRelationRequestDTO.getCode())) {
      userDetail.setCode(userRelationRequestDTO.getCode());
    }
    if (!StringUtils.isEmpty(userRelationRequestDTO.getMobilePhone())) {
      user.setMobilePhone(userRelationRequestDTO.getMobilePhone());
      userDetail.setMobilePhone(userRelationRequestDTO.getMobilePhone());
    }
    if (!StringUtils.isEmpty(userRelationRequestDTO.getEmail())) {
      userDetail.setEmail(userRelationRequestDTO.getEmail());
    }
    if (!StringUtils.isEmpty(userRelationRequestDTO.getFixedTelephone())) {
      userDetail.setFixedTelephone(userRelationRequestDTO.getFixedTelephone());
    }
    if (!StringUtils.isEmpty(userRelationRequestDTO.getPermanentAddress())) {
      userDetail.setPermanentAddress(userRelationRequestDTO.getPermanentAddress());
    }
    if (!StringUtils.isEmpty(userRelationRequestDTO.getCurrentAddress())) {
      userDetail.setCurrentAddress(userRelationRequestDTO.getCurrentAddress());
    }
    if (!StringUtils.isEmpty(userRelationRequestDTO.getMailAddress())) {
      userDetail.setMailAddress(userRelationRequestDTO.getMailAddress());
    }
    if (!StringUtils.isEmpty(userRelationRequestDTO.getPdetailAddress())) {
      userDetail.setPdetailAddress(userRelationRequestDTO.getPdetailAddress());
    }
    if (!StringUtils.isEmpty(userRelationRequestDTO.getCdetailAddress())) {
      userDetail.setCdetailAddress(userRelationRequestDTO.getCdetailAddress());
    }
    if (!StringUtils.isEmpty(userRelationRequestDTO.getMdetailAddress())) {
      userDetail.setMdetailAddress(userRelationRequestDTO.getMdetailAddress());
    }
    this.userMapper.updateByPrimaryKeySelective(user);
    this.userDetailMapper.updateByPrimaryKeySelective(userDetail);
  }

  @Override
  public void updateMobilePhone(String mobilePhone, String id, String phoneCode) {
    Assert.isNotNull(id, ErrorCode.ILLEGAL_PARAMETER, ValidateMessage.ID_NOT_BLANK);
    User user = userMapper.selectByPrimaryKey(id);
    Assert.isNotNull(user, ErrorCode.RESULT_EMPTY, ValidateMessage.ID_NOT_BLANK);
    // 根据手机号和用户类型获取用户信息
    List<User> mobileUser = userMapper.selectByMobilePhoneAndType(mobilePhone, user.getUserType());
    // 判断手机号码是否已经注册
    Assert.isListEmpty(mobileUser, ErrorCode.MOBILE_EXITS);
    Assert.isNotNull(mobilePhone, ErrorCode.ILLEGAL_PARAMETER, ValidateMessage.ID_NOT_BLANK);
    // 从redis获取短信验证码
    String smsCode = redisService.get(RedisKey.SMS_CODE, mobilePhone);
    // 对比redis中的短信验证码
    Assert.isTrue(phoneCode.equals(smsCode), ErrorCode.PHONE_CODE_IS_WRONG);
    user.setMobilePhone(mobilePhone);
    List<UserDetail> userDetailList = userDetailMapper.selectByUserId(id);
    Assert.isNotNull(userDetailList, ErrorCode.RESULT_EMPTY, ValidateMessage.ID_NOT_BLANK);
    UserDetail userDetail = userDetailList.get(0);
    userDetail.setMobilePhone(mobilePhone);
    userMapper.updateByPrimaryKey(user);
    userDetailMapper.updateByPrimaryKey(userDetail);
  }

  @Override
  public void updateEmail(String email, String id, String emailCode) {
    Assert.isNotNull(id, ErrorCode.ILLEGAL_PARAMETER, ValidateMessage.ID_NOT_BLANK);
    User user = userMapper.selectByPrimaryKey(id);
    Assert.isNotNull(user, ErrorCode.RESULT_EMPTY, "该用户不存在");
    List<UserDetail> userDetailList = userDetailMapper.selectByUserId(id);
    Assert.isNotNull(userDetailList, ErrorCode.RESULT_EMPTY, "用户详情信息为空");
    Assert.isNotNull(emailCode, ErrorCode.RESULT_EMPTY, "邮箱验证码为空");
    // 获取redis中邮件验证码
    String emailCodeRedis = redisService.get(RedisKey.EMAIL_CODE, email);
    // 对比redis中的邮件验证码
    Assert.isTrue(emailCode.equals(emailCodeRedis), ErrorCode.EMAIL_CODE_IS_WRONG);
    UserDetail userDetail = userDetailList.get(0);
    userDetail.setEmail(email);
    userDetailMapper.updateByPrimaryKey(userDetail);
  }

  @Override
  public String getPhoneCode(String mobilePhone) {
    // 检查redis是否已有验证码，如果有则直接使用，否则生成新的验证码
    String smsCode = redisService.get(RedisKey.SMS_CODE, mobilePhone);
    if (StringUtils.isBlank(smsCode)) {
      smsCode = generateSMSCode();
      redisService
          .set(RedisKey.SMS_CODE, mobilePhone, smsCode, smsCodeExpireMinutes, TimeUnit.MINUTES);
    }
    Map<String, String> data = new HashMap<>();
    data.put("smsCode", smsCode);
    smsService.send(mobilePhone, SMSEnum.SMS_LOGIN, data);
    return smsCode;
  }

  @Override
  public String getEmailCode(String email) {
    // 检查redis是否已有验证码，如果有则直接使用，否则生成新的验证码
    String emailCode = redisService.get(RedisKey.EMAIL_CODE, email);
    if (StringUtils.isBlank(emailCode)) {
      emailCode = generateSMSCode();
      redisService
          .set(RedisKey.EMAIL_CODE, email, emailCode, smsCodeExpireMinutes, TimeUnit.MINUTES);
    }
    Email emailObject = new Email();
    String[] emailArray = {email};
    // 邮箱
    emailObject.setEmail(emailArray);
    // 主题
    emailObject.setSubject("智慧仲裁注册邮件验证码");
    // 内容
    emailObject.setContent(emailCode);
    iMailService.send(emailObject);
    return emailCode;
  }

  @Override
  public List<UserProxyResponseDTO> getUserProxy(String userId) {
    Assert.isNotNull(userId, ErrorCode.ILLEGAL_PARAMETER, ValidateMessage.ID_NOT_BLANK);
    return userProxyMapper.getUserProxy(userId);
  }

  @Override
  @Transactional(rollbackFor = Exception.class)
  public void updateUserBasic(UserRequestDTO userRequestDTO) {
    Assert.isNotNull(userRequestDTO.getUserId(), ErrorCode.ILLEGAL_PARAMETER,
        ValidateMessage.ID_NOT_BLANK);
    User user = userMapper.selectByPrimaryKey(userRequestDTO.getUserId());
    Assert.isNotNull(user, ErrorCode.RESULT_EMPTY, "用户不存在");
    List<UserDetail> detailList = userDetailMapper.selectByUserId(user.getId());
    Assert.isNotNull(detailList, ErrorCode.RESULT_EMPTY, "用户详情为空");
    UserDetail userDetail = detailList.get(0);
    if (!StringUtils.isEmpty(userRequestDTO.getUserType())) {
      user.setUserType(userRequestDTO.getUserType());
      userDetail.setUserType(userRequestDTO.getUserType());
    }
    if (!StringUtils.isEmpty(userRequestDTO.getUserName())) {
      userDetail.setUserName(userRequestDTO.getUserName());
    }
    if (!StringUtils.isEmpty(userRequestDTO.getSex())) {
      userDetail.setSex(userRequestDTO.getSex());
    }
    if (!StringUtils.isEmpty(userRequestDTO.getCivilFamily())) {
      userDetail.setCivilFamily(userRequestDTO.getCivilFamily());
    }
    if (!StringUtils.isEmpty(userRequestDTO.getResponsibleUser())) {
      userDetail.setResponsibleUser(userRequestDTO.getResponsibleUser());
    }
    if (!StringUtils.isEmpty(userRequestDTO.getResponsiblePhone())) {
      userDetail.setResponsiblePhone(userRequestDTO.getResponsiblePhone());
    }
    if (!StringUtils.isEmpty(userRequestDTO.getLegalUser())) {
      userDetail.setLegalUser(userRequestDTO.getLegalUser());
    }
    if (!StringUtils.isEmpty(userRequestDTO.getLegalUserJob())) {
      userDetail.setLegalUserJob(userRequestDTO.getLegalUserJob());
    }
    if (!StringUtils.isEmpty(userRequestDTO.getCode())) {
      userDetail.setCode(userRequestDTO.getCode());
    }
    if (!StringUtils.isEmpty(userRequestDTO.getMobilePhone())) {
      user.setMobilePhone(userRequestDTO.getMobilePhone());
      userDetail.setMobilePhone(userRequestDTO.getMobilePhone());
    }
    if (!StringUtils.isEmpty(userRequestDTO.getEmail())) {
      userDetail.setEmail(userRequestDTO.getEmail());
    }
    if (!StringUtils.isEmpty(userRequestDTO.getFixedTelephone())) {
      userDetail.setFixedTelephone(userRequestDTO.getFixedTelephone());
    }
    if (!StringUtils.isEmpty(userRequestDTO.getPermanentAddress())) {
      userDetail.setPermanentAddress(userRequestDTO.getPermanentAddress());
    }
    if (!StringUtils.isEmpty(userRequestDTO.getCurrentAddress())) {
      userDetail.setCurrentAddress(userRequestDTO.getCurrentAddress());
    }
    if (!StringUtils.isEmpty(userRequestDTO.getMailAddress())) {
      userDetail.setMailAddress(userRequestDTO.getMailAddress());
    }
    if (!StringUtils.isEmpty(userRequestDTO.getPdetailAddress())) {
      userDetail.setPdetailAddress(userRequestDTO.getPdetailAddress());
    }
    if (!StringUtils.isEmpty(userRequestDTO.getCdetailAddress())) {
      userDetail.setCdetailAddress(userRequestDTO.getCdetailAddress());
    }
    if (!StringUtils.isEmpty(userRequestDTO.getMdetailAddress())) {
      userDetail.setMdetailAddress(userRequestDTO.getMdetailAddress());
    }
    this.userMapper.updateByPrimaryKeySelective(user);
    this.userDetailMapper.updateByPrimaryKeySelective(userDetail);
  }

  @Override
  public List<Map<String, Object>> getPartyType() {
    List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
    for (UserTypeEnum u : UserTypeEnum.values()) {
      if (u.name().equals("PEOPLE")) {
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("name", "自然人");
        map.put("code", u.getCode());
        list.add(map);
      } else if (u.name().equals("COMPANY")) {
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("name", "组织机构");
        map.put("code", u.getCode());
        list.add(map);
      }
    }
    return list;
  }

  @Override
  public void realNameVerify(String userId, String userName, String code) {
    Assert.isNotNull(userId, ErrorCode.ILLEGAL_PARAMETER, ValidateMessage.ID_NOT_BLANK);
    User user = userMapper.selectByPrimaryKey(userId);
    Assert.isNotNull(user, ErrorCode.ILLEGAL_PARAMETER, "用户不存在");
    // 根据姓名和身份证进行实名认证
    boolean verify = verifyService.identityAuthentication(userName, code);
    Assert.isTrue(verify, ErrorCode.NAME_IDCARD_MISMATCHING);
    String isRealName = verify ? VerifyEnum.YES.getCode() : VerifyEnum.NO.getCode();
    user.setIsRealName(isRealName);
    userMapper.updateByPrimaryKeySelective(user);
  }

  /**
   * 验证码规则：6位有效数字
   */
  private String generateSMSCode() {
    Random r = new Random();
    int code = RANDOM_MIN + r.nextInt(RANDOM_MAX);
    return String.valueOf(code);
  }
}
